You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
New json-schema-2020-12-apidom resolve strategy for documents whose root $schema is https://json-schema.org/draft/2020-12/schema (an empty fragment is normalised) and whose root has none of openapi, swagger, asyncapi and arazzo. Any other document keeps the strategy it had (generic for AsyncAPI/Arazzo, refused $schema values and nested-only $schema).
$refs resolve over apidom-reference's json-schema-2020-12 strategies:
against $id base URIs
to $anchor and $dynamicAnchor plain names
to external documents, as in OpenAPI 3.1 Schema Objects
Every $dynamicRef is left in place.
A $ref from a resolved subtree to one of its ancestors ("$ref": "#") is a cycle, so resolveSubtree, Swagger UI's path, works on recursive schemas.
The dereference strategy merges allOf (unless mode: 'strict') and applies modelPropertyMacro, so a schema resolves the same standalone and inside an OpenAPI 3.1 document.
The JSON/YAML parsers detect a document by its parsed root and are used only by this strategy. The OpenAPI parser lists are unchanged, and a regression test covers OpenAPI 3.1 external targets with a root 2020-12 $schema.
Registered before generic in Swagger.resolve and Swagger.resolveSubtree. The parsers and the dereference strategy are exported in Swagger.apidom.
ApiDOM is bumped to 1.13.3 in its own commit. The README, CLAUDE.md and installation docs are updated.
Out of scope: references that cross dialects; bundling; inferring the dialect without $schema. The same ancestor-cycle defect in the OpenAPI 3.1/3.2 strategies is fixed separately in #4304.
Known limitations (apidom-reference, same as OpenAPI 3.1; each pinned by a test.failing fixture):
the uri selector misses a relative $id nested in another relative $id (id-relative-nested);
the $anchor selector also searches embedded $id resources and takes the first match, so a reused anchor name can select the embedded resource's schema (anchor-embedded-resource).
For Swagger UI: import swagger-client/es/resolver/strategies/json-schema-2020-12-apidom into both strategy lists.
Move every @swagger-api/apidom-* package to 1.13.3, add
@swagger-api/apidom-ns-json-schema-2020-12 to dependencies (the JSON Schema
2020-12 resolve strategy imports it) and its two parser adapters to
optionalDependencies, mirroring apidom-reference.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…erge)
Install @swagger-api/apidom-reference and
@swagger-api/apidom-ns-json-schema-2020-12 from tarballs packed from the
ApiDOM branch feat/json-schema-2020-12/phase-3 at commit 11951862a, which
adds the json-schema-2020-12 resolve and dereference strategies and exports
keyMap and getNodeType from the namespace. The tarballs live in
../upstream-tarballs; "$" overrides make nested copies use them.
Drop this commit once ApiDOM releases the branch, and bump every
@swagger-api/apidom-* package to that release.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the json-schema-2020-12-apidom resolve strategy for documents whose root
$schema is https://json-schema.org/draft/2020-12/schema (an empty fragment
normalised) and which have no openapi or swagger field. Any other $schema
keeps the generic strategy. The strategy resolves over apidom-reference's
json-schema-2020-12 strategies, so $refs resolve against $id base URIs,
$anchor and $dynamicAnchor plain names and external documents as in
OpenAPI 3.1 Schema Objects; every $dynamicRef is left in place.
The json-schema-2020-12-swagger-client dereference strategy carries over the
OpenAPI 3.1 Schema Object handling (cycles, $$ref meta patches, collected
errors), merges allOf unless mode is strict and applies modelPropertyMacro,
so a schema resolves the same standalone and inside an OpenAPI 3.1
document. A $ref in the document root keeps its replacement as the parse
result. The JSON and YAML parsers detect a document by its parsed root and
are used only by this strategy; the OpenAPI parser lists are unchanged.
Register the strategy ahead of generic in Swagger.resolve and
Swagger.resolveSubtree, and export the parsers and the dereference strategy
in Swagger.apidom.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record the decisions the 2020-12 work answered (cross-dialect references,
unreleased upstream, content-detecting parsers, $ref to $dynamicAnchor) in
design-and-delivery.md, and in strategy-design.md refract with the
namespace's refract (apidom-ns-arazzo-1 reassigns JSONSchemaElement.refract)
and keep the result class on a dereferenced root.
FOLLOW-UPS: keyMap/getNodeType are exported on the unreleased ApiDOM
branch; new item for apidom-reference's uri selector, which resolves
candidate $id chains against the $ref target instead of the document's
base URI (OpenAPI 3.1 and 3.2 alike).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dereference lineage held only the pathDiscriminator fragment, so a $ref
from the fragment to one of its ancestors was not a cycle: "$ref": "#" in a
recursive schema overflowed the stack when Swagger UI resolved
['properties'] or ['properties', 'children'] through resolveSubtree, and
['properties', 'children', 'items'] returned null. Seed the lineage with
the document root and every element along the pathDiscriminator, so such a
$ref resolves to an absolute $ref, as cycles do everywhere else.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A document is standalone JSON Schema only when its root has the 2020-12
$schema and none of the API description fields openapi, swagger, asyncapi
and arazzo. AsyncAPI and Arazzo documents may declare a root $schema; they
keep the generic strategy they had, which regression tests check by
comparing with a generic-only resolve. The parsers detect through the same
predicate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apidom-reference's $anchor selector searches embedded $id resources too and
takes the first match, so "#tag" can select the embedded resource's schema
instead of the referencing resource's (JSON Schema Core 8.2.2). OpenAPI 3.1
Schema Objects behave the same. Pin it with a test.failing fixture that
starts failing once ApiDOM stops the search at nested $ids.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
State the matching rule as no openapi, swagger, asyncapi or arazzo field
(D18) wherever it appears, record D18 and D19 in design-and-delivery.md,
require the pathDiscriminator lineage in strategy-design.md, and in
FOLLOW-UPS put 2.3 after 2.2 and add 2.4 for apidom-reference's $anchor
selector, which searches embedded schema resources.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The resolver cache reuses a mutated graph, causing subsequent resolutions to retain merged allOf results in strict mode and potentially reuse results from incompatible options.
The script linked the local ApiDOM namespaces and core but left the
published apidom-reference in use, so changes to the upstream resolve
and dereference strategies were not exercised during linked development.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot review of PR #4307 found that the circular replace return skips
indirections.pop() and that the resolve strategy cache reuses a graph
that dereferencing mutates. Both patterns come from the OpenAPI 3.1
strategy, so they are recorded as follow-ups for both.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Dereferencing discards sibling constraints when a reference targets true and misclassifies internal references as external when the root $id matches the retrieval URI, causing incorrect resolution-flag behavior.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Ignore fragments when classifying root $id references
When the root $id equals the retrieval URI, a reference such as #/$defs/User succeeds in uriEvaluate without entering the fallback. This comparison still includes the target fragment, so it marks that internal reference as external: resolve.internal: false dereferences it, while resolve.external: false leaves it unresolved. Compare the fragment-free URIs and extend the existing resolution-flag tests with a root $id case.
A reference to true currently discards every sibling keyword: with $defs.Any: true, { $ref: '#/$defs/Any', type: 'string' } becomes true instead of retaining the string constraint. JSON Schema 2020-12 applies those siblings alongside $ref. Treat a true target as an empty object schema when siblings exist, so the object-merging path preserves them, and add a regression for this case.
normalize was the identity function. Inline it in the strategy, since
resolveSubtree still calls strategy.normalize, and remove the dead
skipNormalization branch from resolve.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
json-schema-2020-12-apidomresolve strategy for documents whose root$schemaishttps://json-schema.org/draft/2020-12/schema(an empty fragment is normalised) and whose root has none ofopenapi,swagger,asyncapiandarazzo. Any other document keeps the strategy it had (genericfor AsyncAPI/Arazzo, refused$schemavalues and nested-only$schema).$refs resolve over apidom-reference's json-schema-2020-12 strategies:$idbase URIs$anchorand$dynamicAnchorplain names$dynamicRefis left in place.$reffrom a resolved subtree to one of its ancestors ("$ref": "#") is a cycle, soresolveSubtree, Swagger UI's path, works on recursive schemas.allOf(unlessmode: 'strict') and appliesmodelPropertyMacro, so a schema resolves the same standalone and inside an OpenAPI 3.1 document.$schema.genericinSwagger.resolveandSwagger.resolveSubtree. The parsers and the dereference strategy are exported inSwagger.apidom.Out of scope: references that cross dialects; bundling; inferring the dialect without
$schema. The same ancestor-cycle defect in the OpenAPI 3.1/3.2 strategies is fixed separately in #4304.Known limitations (apidom-reference, same as OpenAPI 3.1; each pinned by a
test.failingfixture):uriselector misses a relative$idnested in another relative$id(id-relative-nested);$anchorselector also searches embedded$idresources and takes the first match, so a reused anchor name can select the embedded resource's schema (anchor-embedded-resource).For Swagger UI: import
swagger-client/es/resolver/strategies/json-schema-2020-12-apidominto both strategy lists.🤖 Generated with Claude Code